home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Hot Mix 17
/
Hot Mix 17.iso
/
HM17_SGI
/
research
/
lib
/
read_bmp.pro
< prev
next >
Wrap
Text File
|
1997-07-08
|
7KB
|
223 lines
; $Id: read_bmp.pro,v 1.9 1997/03/12 20:46:43 stevep Exp $
;
; Copyright (c) 1993-1997, Research Systems, Inc. All rights reserved.
; Unauthorized reproduction prohibited.
FUNCTION READ_BMP, File, Red, Green, Blue, Ihdr, RGB=rgb
; Copyright (c) 1993, Research Systems, Inc. All rights reserved.
; Unauthorized reproduction prohibited.
;+
; NAME:
; READ_BMP
;
; PURPOSE:
; This function reads a Microsoft Windows Version 3 device
; independent bitmap file (.BMP).
;
; CATEGORY:
; Input/Output
;
; CALLING SEQUENCE:
; Result = READ_BMP(File [, R, G, B [, IHDR]])
;
; INPUTS:
; File: The full path name of the bitmap file to read.
;
; OUTPUTS:
; This function returns a byte array containing the image
; from the bitmap file. In the case of 4-bit or 8-bit images,
; the dimensions of the resulting array are [biWidth, biHeight];
; for 16 and 24-bit decomposed color images the dimensions are
; [3, biWidth, biHeight].
; Dimensions are taken from the BITMAPINFOHEADER of the file.
; NOTE: for 24 bit images, unless the RGB keyword is supplied,
; color interleaving is blue, green, red;
; i.e. result[0,i,j] = blue, result[1,i,j] = green, etc.
;
; OPTIONAL OUTPUTS:
; R, G, B: Color tables from the file. There 16 elements each for
; 4 bit images, 256 elements each for 8 bit images. Not
; defined or used for 16 and 24 bit images.
; Ihdr: A structure containing BITMAPINFOHEADER from file.
; Tag names are as defined in the MS Windows Programmer's
; Reference Manual, Chapter 7.
;
; KEYWORDDS:
; RGB: If this keyword is supplied, and a 16 or 24-bit image is read,
; color interleaving of the result is R, G, B, rather than BGR.
; Result[0,i,j] = red, Result[1,i,j] = green, and
; Result[2,i,j] = blue.
; SIDE EFFECTS:
; IO is performed.
;
; RESTRICTIONS:
; DOES NOT HANDLE: 1 bit deep images, or compressed images.
; Is not fast for 4 bit images. Works best on images where the
; number of bytes in each scan-line is evenly divisible by 4.
;
; PROCEDURE:
; Straightforward. Will work on both big endian and little endian
; machines.
;
; EXAMPLE:
; TV, READ_BMP('c:\windows\party.bmp', r, g, b) ;Read & display image
; TVLCT, r, g, b ;Load it's colors
;
; MODIFICATION HISTORY:
; DMS, RSI. March 1993. Original version.
; DMS, RSI. May, 1993. Now works on all machines...
; DMS, RSI. Nov, 1996 Added support for 16-bit RGB and RGB keyword.
;-
on_ioerror, bad
on_error, 2 ;Return on error
openr, unit, file, /GET_LUN, /BLOCK
fhdr = { BITMAPFILEHEADER, $
bftype: bytarr(2), $ ;A two char string
bfsize: 0L, $
bfreserved1: 0, $
bfreserved2: 0, $
bfoffbits: 0L $
}
readu, unit, fhdr ;Read the bitmapfileheader
if string(fhdr.bftype) ne "BM" then begin
free_lun,unit
message, 'File '+file+' is not in bitmap file format'
endif
ihdr = { BITMAPINFOHEADER, $
bisize: 0L, $
biwidth: 0L, $
biheight: 0L, $
biplanes: 0, $
bibitcount: 0, $
bicompression: 0L, $
bisizeimage: 0L, $
bixpelspermeter: 0L, $
biypelspermeter: 0L, $
biclrused: 0L, $
biclrimportant: 0L $
}
readu, unit, ihdr
big_endian = (byte(1,0,2))[0] eq 0b
if big_endian then begin ;Big endian machine?
fhdr = swap_endian(fhdr) ;Yes, swap it
ihdr = swap_endian(ihdr)
endif
if ihdr.bibitcount eq 1 then begin
free_lun, unit
message, 'Can''t handle monochrome images'
endif
if ihdr.bicompression ne 0 then begin
free_lun, unit
message, 'Can''t handle compressed images'
endif
;Pseudo color?
if (ihdr.bibitcount ne 24) and (ihdr.bibitcount ne 16) then begin
colors = bytarr(4, 2^ihdr.bibitcount)
readu, unit, colors ;Read colors
red = reform(colors[2, *]) ;Decommutate colors
green = reform(colors[1, *])
blue = reform(colors[0, *])
endif
nx = ihdr.biwidth ;Columns
ny = ihdr.biheight ;Rows
point_lun, unit, fhdr.bfoffbits ;Point to data...
case ihdr.bibitcount of ;How many bits/pixel?
4: begin
a = bytarr(nx, ny, /nozero)
buff = bytarr(nx/2, /nozero) ;Line buffer
even = lindgen(nx/2) * 2
odd = even + 1
if nx and 1 then pad = 0B ;interbyte padding
i = (n_elements(buff) + n_elements(pad)) and 3 ;bytes we have
if i ne 0 then pad = bytarr(4-i+n_elements(pad))
for i=0, ny-1 do begin
if n_elements(pad) ne 0 then readu, unit, buff, pad $
else readu, unit, buff
a[even, i] = ishft(buff, -4)
a[odd, i] = buff and 15b
if nx and 1 then a[nx-1, i] = ishft(pad[0], -4) ;Last odd byte?
endfor
endcase
8: begin
a = bytarr(nx, ny, /nozero)
if (nx and 3) eq 0 then readu, unit, a $ ;Slam dunk it
else begin ;Must read line by line...
pad = bytarr(4 - (nx and 3))
buff = bytarr(nx, /nozero)
for i=0, ny-1 do begin ;Each line
readu, unit, buff, pad
a[0,i] = buff
endfor
endelse
endcase ;8 bits/pixel
16: begin ;16 bits/pixel
; bits(0:4) = blue
; bits(5:9) = green
; bits(10:14) = red
a = intarr(nx * ny, /nozero) ;Read as a 1D array
if (nx and 1) eq 0 then readu, unit, a $ ;If even # of cols, no padding
else begin
pad = 0 ;Pad 1 16 bit word
buff = intarr(nx, /nozero)
for i=0, ny-1 do begin
readu, unit, buff, pad
a[i * nx] = buff ;Insert line
endfor
endelse
if big_endian then byteorder, a, /sswap
r = byte(ishft(a,-7) and 248) ;Shift down 10 and up 3
g = byte(ishft(a,-2) and 248) ;down 5 and up 3
a = byte(ishft(a, 3) and 248) ;up 3, really blue
if keyword_set(RGB) then a = [r,g,a] $ ;Unswitch it?
else a = [a,g,r]
a = reform(a, nx * ny, 3, /overwrite) ;Diddle to 3,nx,ny
a = transpose(temporary(a)) ;Color interleave in 1st dimension
a = reform(a,3,nx,ny,/overwrite)
endcase ;16 bits
24: begin ;24 bits / pixel....
a = bytarr(3, nx, ny, /nozero)
if ((3 * nx) and 3) eq 0 then readu, unit, a $ ;Again, dunk it.
else begin
pad = bytarr(4 - ((3 * nx) and 3))
buff = bytarr(3, nx, /nozero)
for i=0, ny-1 do begin
readu, unit, buff, pad
a[0,0, i] = buff ;Insert line
endfor
endelse
if keyword_set(RGB) then begin ;Unswitch it?
buff = a[0,*,*]
a[0,0,0] = a[2,*,*]
a[2,0,0] = buff
endif
endcase ;24bits
else: begin
free_lun,unit
Message,'Can not handle '+strtrim(ihdr.bibitcount,2)+' bits/pixel'
endcase
endcase
free_lun, unit
return, a
bad: if n_elements(unit) gt 0 then free_lun, unit
Message, 'Can''t open (or read)' + file
return, 0
end